home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Development Platforms / LISP Related / U. Mass AI & LISP Tools / MODULES / RULES / Rule-Back.lisp next >
Encoding:
Text File  |  1990-06-25  |  45.5 KB  |  925 lines  |  [TEXT/CCL ]

  1. ; (c) Copyright 1990 by University of Massachusetts. All rights reserved.
  2. ; This software was conceived, designed, and written by Dan Suthers 
  3. ; while supported by the National Science Foundation under grant number
  4. ; MDR 8751362, and by a fellowship from Apple Computer, Inc., Cupertino,
  5. ; CA.  Partial support was also received from the Office of Naval Research
  6. ; under a University Research Initiative Grant, contract N00014-86-K-0764.
  7. ; Mr. Suthers created this software under his own initiative while in an 
  8. ; academic relationship with the University of Massachusetts.  The above
  9. ; copyright notice was a condition placed by University lawyers on approval
  10. ; of distribution of this software by Apple Computer, and is not meant to
  11. ; imply that this software was created in an employment or "work for hire"
  12. ; relationship between the University and Mr. Suthers.
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14. ; File:         Rule-Back.lisp
  15. ; Author:       Dan Suthers
  16. ; Created:      19-Oct-88 21:57:32
  17. ; Modified:     22-Jun-90 02:24:58 (Dan Suthers)
  18. ; Language:     Common Lisp
  19. ; Package:      RULE
  20. ;
  21. ; Description:  Rule-based reasoner built on the pattern matching facilities
  22. ;               of DNET.  Supports forward and backward reasoning.
  23. ;
  24. ;               This file contains only code for back chaining.  See also
  25. ;               Rule-Defs, Rule-Build, and Rule-Forward.
  26. ;               File RULES has documentation.
  27. ;
  28. ; (c) Copyright 1988, by Daniel D. Suthers
  29. ;                        Department of Computer and Information Science
  30. ;                        University of Massachusetts
  31. ;                        Amherst, Massachusetts 01003
  32. ;
  33. ; This software was conceived, designed, and written by Dan Suthers 
  34. ; while supported by the National Science Foundation under grant number
  35. ; MDR 8751362, and by a fellowship from Apple Computer, Inc., Cupertino,
  36. ; CA.  Partial support was also received from the Office of Naval Research
  37. ; under a University Research Initiative Grant, contract N00014-86-K-0764.
  38. ; I wish to acknowledge the generous support of Beverly Woolf, who obtained 
  39. ; the above grants and encouraged me to pursue my own research interests in
  40. ; her lab.  This work would not have been possible without the resources and
  41. ; stimulating environment of the Computer and Information Science department.
  42. ;
  43. ; Permission to use, modify, and distribute this software is granted subject 
  44. ; to the following restrictions and understandings:
  45. ; 1. The file header, including this notice, shall be retained, and may be
  46. ;    extended to include documentation of modifications to the software.
  47. ; 2. This material is for nonprofit educational and research purposes only.
  48. ;    Users are requested, but not required, to inform Mr. Suthers of any 
  49. ;    noteworthy uses of this software.
  50. ; 3. Mr. Suthers and the University of Massachusetts make no warrantee or
  51. ;    representation that the operation of this software will be error free,
  52. ;    and are under no obligation to provide any services.
  53. ; 4. Any user of such software agrees to indemnify and hold harmless Mr.
  54. ;    Suthers and the University of Massachusetts from all claims arising 
  55. ;    out of the use or misuse of this software, or arising out of any 
  56. ;    accident, injury, or damage whatsoever, and from all costs, counsel
  57. ;    fees, and liabilities incurred in or about any such claim, action, or
  58. ;    proceeding brought thereon.
  59. ; 5. All materials and reports developed as a consequence of the use of 
  60. ;    this software shall duly acknowledge such use, in accordance with
  61. ;    the usual standards of acknowledging credit in academic research.
  62. ;
  63. ; Status: Working.  Could use efficiency hacks and added functionality.
  64. ;
  65. ; Changes:
  66. ;   16-Dec-88 To prevent circularity, backchaining not allowed on a rule
  67. ;     with the same bindings already active.
  68. ;   26-Dec-88 Multiple changes to deal with bug in SUPPORT, which was not
  69. ;     substituting subgoal bindings into consequent match bindings, with 
  70. ;     the result that :BIND in an :AND tried to evaluate an unbound variable.
  71. ;   27-Mar-89 Total rewrite.  Eliminated redundant functions and reasoning;
  72. ;     Added SUPPORTED function and :SEQ operator; Near Miss processing of
  73. ;     :AND; and various bugs fixed.
  74. ;   13-Apr-89 Use of dnet::match-internal and dnet:unify replaced with
  75. ;     match-rules and fast-bind, to take advantage of what is known about
  76. ;     matching rules to speed things up.
  77. ;   26-Apr-89 Fixed :OR support tree (which was improperly adjoining arcs).
  78. ;   19-Sep-89 Fixed :LISP SUPPORT bug: TRJ-ARC-MODALITY made all :LISPs 
  79. ;     supported, regardless of outcome. 
  80. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  81. ;
  82. ; To Do:
  83. ;   Improve datum-justification breakdown for conjunctive datum.
  84. ;
  85. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  86. ;
  87. ;                              Program Notes
  88. ;
  89. ; On Transitive Bindings:
  90. ; At one point I thought I needed a version of SUBSTITUTE-BINDINGS, called
  91. ; SUBSTITUTE-TRANSITIVE-BINDINGS, which iterated the substitution until no
  92. ; more occurred.  This was to deal with ((?:x . ?:y) (?:y . <constant>)).
  93. ; While UNIFY can return such a binding set, I now believe the backchaining
  94. ; code will not allow it.  This arose only because SUPPORT was APPENDING
  95. ; the bindings that matched a goal to a consequent (yielding (?:x . ?:y)) 
  96. ; with those by which the antecedent subgoal was satisfied ((?:y . <constant>)),
  97. ; to give the above "transitive" binding set.  This was a mistake: now SUPPORT
  98. ; works like RETRIEVE by SUBSTITUTING the latter bindings into the former,
  99. ; to yield ((?:x . <constant>)).  Hence, given there are no variables in the
  100. ; data base, direct retrieval from the database cannot produce transitive
  101. ; bindings, and as I've just shown the rule chainer will eliminate all such
  102. ; bindings it produces.
  103. ;
  104. ; On Finding the First Result:
  105. ;
  106. ; I had a parameter :FIND-ALL for the RETRIEVE function.  If NIL, I'd stop
  107. ; at the first result found.  This does not work.  You don't know which way
  108. ; of getting a subgoal will yield bindings consistent with later subgoals,
  109. ; so you need to return all of them for use by other retrieval functions.
  110. ; If you want only some result, you could save consing by writing a version
  111. ; of RETRIEVE which only does substitute-bindings to get the results for 
  112. ; one of the binding sets returned from RETRIEVE-BINDINGS. 
  113. ;
  114. ; On assumptions enabling FAST-BIND:
  115. ;
  116. ; This replaces DNET:UNIFY when processing result of dnet::match-links
  117. ; for retrieval of backchaining rules.  We rely on what we know about 
  118. ; this matching to use a faster function:
  119. ;
  120. ; 1. The two patterns will always correspond element-wise, i.e. atomic 
  121. ;    non-variables have already been verified to be equal by match-links,
  122. ;    each sublist has the same number of elements, etc.  (We don't use 
  123. ;    dotted endings in rules.) 
  124. ; 2. Variables in each pattern are assumed to be unique and are treated
  125. ;    as such, even if they have the same name.  (This can be done because
  126. ;    we return two binding sets, one for each direction of binding.)
  127. ;    In particular, ?:x in pattern-1 can be bound to ?:x in pattern-2
  128. ;    because each occurance of ?:x is distinct, and we never have to check
  129. ;    for whether a variable occurs inside an expression it is being bound
  130. ;    to.  This will never cause trouble because:
  131. ;    a. Variables ARE unique symbols across rules, so the only way a
  132. ;       symbol will occur in both patterns is if a rule re-invokes itself.
  133. ;    b. We check for circular rule invocations by testing the entire 
  134. ;       binding set against previous sets on active-bindings.
  135. ;    c. Hence the only time a variable symbol will occur in both patterns
  136. ;       is when a rule re-invokes itself with some (but not all) bindings
  137. ;       repeated, so a rule variable will be bound to itself by fast-bind.
  138. ;       It is placed on only one binding list (the first one returned). 
  139. ; 3. As a consequence of 1 and 2, the only way two patterns can fail to 
  140. ;    match is inconsistent binding of a variable in one direction.  Other 
  141. ;    than checking for this, all we have to do is record the bindings. 
  142. ;
  143. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  144.  
  145. (in-package :RULE)
  146.  
  147. (export '(
  148.  
  149.           *support-tree*
  150.  
  151.           retrieve
  152.           support
  153.  
  154.           trj-arc
  155.           trj-arc-p
  156.           trj-arc-bindings
  157.           trj-arc-grounds
  158.           trj-arc-modality
  159.           trj-arc-warrant
  160.  
  161.  
  162.           trj-node
  163.           trj-node-p
  164.           trj-node-bindings
  165.           trj-node-claim
  166.           trj-node-modality
  167.           trj-node-support
  168.  
  169.           ))
  170.  
  171. (require :mappings)
  172. (require :rule-defs)
  173. #+:CCL (require :rule-browser)
  174.  
  175. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  176. ;;;
  177. ;;;                              DATA STRUCTURES
  178. ;;;
  179. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  180.  
  181. (deftype boolean () '(or T null))
  182.  
  183. (defstruct TRJ-NODE
  184.   "Nodes of a tree representing the support generated by backchaining.
  185.     CLAIM:    an expression we are trying to support at this node.
  186.     MODALITY: one of :SUPPORTED or :UNSUPPORTED.
  187.     SUPPORT:  list of TRJ-ARC structures, forming an implicit disjunction."
  188.  
  189.   (CLAIM nil :type list)
  190.   (MODALITY :unsupported :type (member :supported :unsupported))
  191.   (SUPPORT nil :type list))
  192.  
  193. (defstruct TRJ-ARC 
  194.   "Each of these represents one way in which support for a TRJ-NODE has been 
  195.   attempted, by branching to supporting nodes.
  196.     WARRANT: one of :ASSERTED, :AND, :SEQ, :OR, :LISP, :BIND, or a rule name.
  197.     GROUNDS: a list, or a list of lists, of TRJ-NODEs, depending on the CLAIM.
  198.     BINDINGS: a binding set or a list of binding sets.
  199.   :AND, :SEQ for a TRJ-NODE claim of <c1> ... <cN> have grounds ((<g1> ... <gN>))
  200.     and one binding set.
  201.   :OR for claim <d1> ... <dN> has grounds ((<g1> ... <gN>)) and a list of binding 
  202.     sets.
  203.   :BIND for <variable> <expression> has a single binding set binding only the
  204.     <variable>, and <expression> as grounds.
  205.   :LISP for <expression> has null binding set and a TRJ-NODE recording success
  206.     or failure of the expression.
  207.   <Rule> has (<g1> ... <gn>) grounds and a list of respective 
  208.     unifications between the consequent and the claim as bindings.
  209.   :ASSERTED for <pattern> has <expression> as grounds and binding is the single
  210.     binding set unifying the two."
  211.  
  212.   (WARRANT nil :type symbol)
  213.   (GROUNDS nil :type list)
  214.   (BINDINGS nil :type list))
  215.  
  216. ;;; Ways to make nodes and arcs look like they have each other's fields.
  217.  
  218. (defun TRJ-ARC-MODALITY (arc)
  219.   "trj-arc-modality <arc>                                           [Function]
  220.   Returns :supported or :unsupported, depending on the arc's warrant and
  221.   whether there are nodes on the arc's grounds which provide support via
  222.   that warrant. (Eg. for :and, all grounds must be :supported; for :or or
  223.   a rule, at least one must be.)  No argument checking."
  224.   (declare (optimize (safety 1) (space 2) (speed 3)))
  225.   (case (trj-arc-warrant arc)
  226.     ((:asserted :bind) :supported)
  227.     ((:and :seq)
  228.      (if (every #'(lambda (n) (declare (type trj-arc n))
  229.                    (eq (trj-node-modality n) :supported))
  230.                 (trj-arc-grounds arc))
  231.        :supported
  232.        :unsupported))
  233.     ((:lisp)
  234.      (if (eq (trj-node-modality (first (trj-arc-grounds arc))) :supported)
  235.        :supported
  236.        :unsupported))
  237.     ;; Both :OR and rules are disjunctive (rule only has to succeed one way).
  238.     (otherwise
  239.      (if (some #'(lambda (n) (declare (type trj-arc n))
  240.                    (eq (trj-node-modality n) :supported))
  241.                (trj-arc-grounds arc))
  242.        :supported
  243.        :unsupported))))
  244.  
  245. (defun TRJ-NODE-BINDINGS (node)
  246.   "trj-node-bindings <node>                                         [Function]
  247.   Returns a list of binding sets, which includes only the bindings by 
  248.   which <node> succeeds.  No argument checking."
  249.   (declare (optimize (safety 1) (space 2) (speed 3)))
  250.   (mapcan #'(lambda (a) (declare (type trj-arc a))
  251.             (if (eq (trj-arc-modality a) :supported)
  252.               (list (trj-arc-bindings a))))
  253.          (trj-node-support node)))
  254.  
  255. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  256. ;;;
  257. ;;;                      INTERNAL FUNCTIONS AND MACROS
  258. ;;;
  259. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  260.  
  261. ;;; Little Helpers
  262.  
  263. (eval-when (compile eval)
  264.  
  265.   (defmacro LISP-EVAL (forms)
  266.     ;; Escape to LISP: Want to return result of the last form evaluated.  No 
  267.     ;; bindings ever needed, since they're already substituted by backchaining. 
  268.     ;; Making this a macro in case I want to put trace or error protection in. 
  269.     `(eval (cons 'progn ,forms)))
  270.  
  271.   (defmacro SECOND-VALUE (multiple-value-call)
  272.     ;; Return second of two values.
  273.     `(multiple-value-bind
  274.        (first-value second-value)
  275.        ,multiple-value-call
  276.        (declare (ignore first-value))
  277.        second-value))
  278.  
  279.   (defmacro EXTEND-ACTIVE-BINDINGS (bindings1 bindings2 active-bindings)
  280.     ;; Extends the active-bindings list tested by circular bindings.
  281.     `(if (or ,bindings1 ,bindings2)
  282.        (cons (cons ,bindings1 ,bindings2) ,active-bindings)
  283.        ,active-bindings))
  284.  
  285.   (defmacro CIRCULAR-BINDINGS (bindings1 bindings2 active-bindings pattern-p)
  286.     ;; Returns T iff the bindings indicate an active rule has directly or
  287.     ;; indirectly reinvoked itself.
  288.     `(if (or ,bindings1 ,bindings2)
  289.        ;; There are bindings: see if they are active.  Since variables
  290.        ;; are unique to rules, don't have to index active-bindings by rule.
  291.        (member (cons ,bindings1 ,bindings2) ,active-bindings :test #'equal)
  292.        ;; Bindings NIL OK only if there are no variables in goal.  Some
  293.        ;; rules can generate subgoals with same variables as the rule's
  294.        ;; consequent. These subgoals bind to consequent with NIL bindings.
  295.        ,pattern-p))
  296.  
  297.   (defmacro TRACE-BACKWARD-RULE (goal rule-record bindings)
  298.     ;; Print a trace of a backwards application of a rule, if turned on.
  299.     `(if *rule-trace*
  300.        #-:CCL (format *rule-trace* "~&B: ~S <-- ~S -- ~S"
  301.                       ,goal (rule-record-rule-name ,rule-record)
  302.                       (substitute-bindings ,bindings 
  303.                                            (rule-record-pattern ,rule-record)))
  304.        #+:CCL (rule-trace "~&B: ~S <-- ~S -- ~S"
  305.                           ,goal (rule-record-rule-name ,rule-record)
  306.                           (substitute-bindings ,bindings 
  307.                                                (rule-record-pattern ,rule-record)))
  308.        ))
  309.  
  310.   (defmacro MATCH-RULES (goal rules-dnet)
  311.     ;; This imitates dnet::match-internal, the main difference being 
  312.     ;; the use of fast-bind instead of dnet:unify.
  313.     `(let ((consequents nil) (consequent-bindings nil) (reverse-bindings nil))
  314.        (declare (list consequents consequent-bindings reverse-bindings))
  315.        (setf (cdr *consequent-template*) ,goal)
  316.        (dolist (link (the list
  317.                           (dnet::match-links *consequent-template*
  318.                                              (list (dnet::dnet-link
  319.                                                     (the dnet (sm:gets 'dnet ,rules-dnet)))))))
  320.          (declare (list link))
  321.          (multiple-value-bind
  322.            (success binding-1 binding-2)
  323.            (fast-bind *consequent-template* 
  324.                       (dnet-terminal-expr (cdr link)) nil nil)
  325.            (declare (symbol success) (list binding-1 binding-2))
  326.            (when success
  327.              (push (dnet-terminal-expr (cdr link)) consequents)
  328.              (push binding-1 consequent-bindings)
  329.              (push binding-2 reverse-bindings))))
  330.        (values consequents consequent-bindings reverse-bindings)))
  331.  
  332.   ) ; eval-when
  333.  
  334. ;;;-------------------------------------------------------------------
  335. ;;; Maintaining lists of support arcs.
  336.  
  337. (defun MERGE-SUPPORT-ARCS (arcs1 arcs2)
  338.   ;; Unions two lists of support arcs, merging arcs whose warrant and bindings
  339.   ;; are the same, diving in recursively as needed.
  340.   (dolist (arc arcs2 arcs1)
  341.     (declare (type trj-arc arc))
  342.     (setf arcs1 (adjoin-support-arc arc arcs1))))
  343.  
  344. (defun ADJOIN-SUPPORT-ARC (arc arc-list)
  345.   ;; Adds a support arc to a set of arcs. The arc is already a "member" if
  346.   ;; an arc with the same warrant and bindings is.  In that case, merge the
  347.   ;; grounds recursively; else add the arc to the arc-list.
  348.   (let* ((matching-arc
  349.           (first (member arc arc-list
  350.                          :test #'(lambda (a1 a2)
  351.                                    (declare (type trj-arc a1 a2))
  352.                                    (and (eq (trj-arc-warrant a1) 
  353.                                             (trj-arc-warrant a2))
  354.                                         (equal (trj-arc-bindings a1)
  355.                                                (trj-arc-bindings a2))))))))
  356.     (declare (type trj-arc arc))
  357.     (cond (matching-arc
  358.            (setf (trj-arc-grounds matching-arc)
  359.                  (merge-support-arcs (trj-arc-grounds matching-arc)
  360.                                      (trj-arc-grounds arc)))
  361.            arc-list)
  362.           (t (setq arc-list (nconc arc-list (list arc)))))))
  363. ;;;(push arc arc-list)))))
  364.  
  365. ;;;-------------------------------------------------------------------
  366. ;;; Special purpose unification.  See program notes.
  367.  
  368. (defun FAST-BIND (pattern-1 pattern-2 bindings-1 bindings-2)
  369.   ;; Assumes that pattern-1 and pattern-2 correspond element wise, and
  370.   ;; the only way the binding can fail is if one variable is bound more 
  371.   ;; than once, to different elements in the other pattern. 
  372.   (declare (list bindings-1 bindings-2) 
  373.            (optimize (safety 1) (space 2) (speed 3)))
  374.   (cond ((variable-p pattern-1)
  375.          (let ((prev-binding (assoc pattern-1 bindings-1)))
  376.            (if prev-binding
  377.              (if (equal (cdr prev-binding) pattern-2)
  378.                (values t bindings-1 bindings-2)
  379.                (values nil nil nil))
  380.              (values t (cons (cons pattern-1 pattern-2) bindings-1) bindings-2))))
  381.         ((variable-p pattern-2)
  382.          (let ((prev-binding (assoc pattern-2 bindings-2)))
  383.            (if prev-binding
  384.              (if (equal (cdr prev-binding) pattern-1)
  385.                (values t bindings-1 bindings-2)
  386.                (values nil nil nil))
  387.              (values t bindings-1 (cons (cons pattern-2 pattern-1) bindings-2)))))
  388.         ;; If one is a non-variable atom, match-links guarantees the other is an
  389.         ;; equal atom.
  390.         ((atom pattern-1)
  391.          (values t bindings-1 bindings-2))
  392.         (T
  393.          (multiple-value-bind
  394.            (car-success extended-bindings-1 extended-bindings-2)
  395.            (fast-bind (car pattern-1) (car pattern-2) bindings-1 bindings-2)
  396.            (declare (list extended-bindings-1 extended-bindings-2))
  397.            (if car-success
  398.              (fast-bind (cdr pattern-1) (cdr pattern-2) 
  399.                         extended-bindings-1 extended-bindings-2)
  400.              (values nil nil nil))))))
  401.  
  402. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  403. ;;; Backward Chaining
  404.  
  405. ;;;------------------------------------------------------------------------
  406. ;;; Version which returns results like MATCH, without constructing support.
  407.  
  408. (defun RETRIEVE-BINDINGS (goal data-dnet rules-dnet active-bindings)
  409.   ;; Returns all binding sets by which <goal> is satisfied.  Active-bindings
  410.   ;; are currently in effect for backchained rules, used to avoid circularity.
  411.   (declare (list goal active-bindings) (symbol data-dnet rules-dnet)
  412.            (optimize (safety 1) (space 2) (speed 3)))
  413.   (case (first goal)
  414.     ((:and :seq)
  415.      ;; These are treated the same by RETRIEVE, but not by SUPPORT.
  416.      (retrieve-and (rest goal) data-dnet rules-dnet nil active-bindings))
  417.     ((:or)
  418.      (retrieve-or (rest goal) data-dnet rules-dnet active-bindings))
  419.     ((:lisp) 
  420.      ;; Must signal success or failure based on whether result is T or nil.
  421.      ;; Success is an empty binding set: (()); and failure is no binding set: ().
  422.      (if (lisp-eval (rest goal)) (list nil) nil))
  423.     ((:bind)
  424.      ;; The form introduces a new variable.  Assumes that all variables in
  425.      ;; the form to evaluate have been bound.  Return a set of one binding.
  426.      (list (list (cons (second goal) (lisp-eval (cddr goal))))))
  427.     (otherwise
  428.      ;; Combine results from direct match to data-dnet with backchaining results.
  429.      ;; Since only the bindings are needed, call PATTERN-MATCH-LINKS directly 
  430.      ;; instead of MATCH-PATTERN-INTERNAL: this requires duplicating some of the 
  431.      ;; latter's link processing code (see DNET).
  432.      (nconc (mapcar #'(lambda (link) (declare (list link))
  433.                        (second-value
  434.                         (bind-vars goal (dnet-terminal-expr (cdr link)) nil)))
  435.                     (dnet::pattern-match-links
  436.                      goal (list (dnet::dnet-link (sm:gets 'dnet data-dnet)))))
  437.             (retrieve-backchain goal data-dnet rules-dnet active-bindings)))))
  438.  
  439. (defun RETRIEVE-BACKCHAIN (goal data-dnet rules-dnet active-bindings)
  440.   ;; Returns bindings which result from backchaining on the goal.
  441.   (declare (list goal active-bindings)
  442.            (symbol data-dnet rules-dnet) 
  443.            (optimize (safety 1) (space 2) (speed 3)))
  444.  
  445.   ;; Find matching consequents.  Iterate over each of their antecedents (recorded
  446.   ;; in rule-records).  This iteration is over an implicit disjunction, and each 
  447.   ;; consequent & antecedent pair may support new data independently of others.
  448.   (multiple-value-bind
  449.     (consequents consequent-bindings reverse-bindings)
  450.     (match-rules goal rules-dnet)
  451.     (declare (list consequents consequent-bindings reverse-bindings))
  452.  
  453.     ;; Loop for consequents matched, returning binding sets accumulated.
  454.     (do ((cptr consequents         (rest cptr))
  455.          (bptr consequent-bindings (rest bptr))
  456.          (rptr reverse-bindings    (rest rptr))
  457.          (goal-has-variables (pattern-p goal))
  458.          (binding-sets (list :head)))
  459.         ((null cptr) (rest binding-sets))
  460.       (declare (list cptr bptr rptr binding-sets))
  461.  
  462.       ;; Loop for antecedents indexed under this consequent.
  463.       (dolist (rule-record (dnet::expr-info-internal (first cptr) rules-dnet))
  464.         (declare (list rule-record))
  465.         
  466.         ;; The following avoids circularity in rules by preventing repeated bindings.
  467.         (unless (circular-bindings (first bptr) (first rptr) 
  468.                                    active-bindings goal-has-variables)
  469.           (trace-backward-rule goal rule-record (first bptr))
  470.  
  471.           ;; Make appropriate subgoal expression by substituting bindings into
  472.           ;; the current antecedent (the rule-record-pattern), and get bindings
  473.           ;; which satisfy this subgoal.  Then construct bindings to return by 
  474.           ;; substituting these subgoal bindings (which satisfied the antecedent) 
  475.           ;; into consequent bindings (by which the goal matched the backchaining 
  476.           ;; rule).  Consequent bindings has cdr-references to rule variables 
  477.           ;; which are bound in the subgoal bindings, and hence replaced by this 
  478.           ;; substitution.
  479.           (nconc binding-sets
  480.                  (mapcar #'(lambda (subgoal-binding)
  481.                              (declare (list subgoal-binding))
  482.                             (utils:compose-mappings (first bptr) subgoal-binding))
  483.                          (retrieve-bindings
  484.                           (substitute-bindings (first rptr)
  485.                                                (rule-record-pattern rule-record))
  486.                           data-dnet rules-dnet 
  487.                           (extend-active-bindings (first bptr) (first rptr) active-bindings)))))))))
  488.  
  489. (defun RETRIEVE-AND (and-goals data-dnet rules-dnet previous-bindings active-bindings)
  490.   ;; Return all sets of bindings satisfying an :AND or :SEQ expression.
  491.   ;; This is tricky because we have to deal with both multiple ways to satisfy
  492.   ;; each conjunct and ensuring that bindings are consistent across conjuncts.
  493.   ;; (Previous-bindings are from earlier conjuncts in the :and expression, while 
  494.   ;; active-bindings are from active rules.)
  495.   (declare (list and-goals previous-bindings active-bindings) 
  496.            (symbol data-dnet rules-dnet) (optimize (safety 1) (space 2) (speed 3)))
  497.   (if (null and-goals)
  498.     ;; Nothing left to do, but we expected the single previous-bindings to be
  499.     ;; expanded into a set of its extensions, so list it to make a set.
  500.     (list previous-bindings)
  501.     ;; Find all ways to satisfy the first conjunct.  (Previous bindings are assumed
  502.     ;; to have already been substituted into remaining conjuncts, which guarantees
  503.     ;; consistency.)  Extend the previous bindings with each resulting extension
  504.     ;; to the bindings, and recurse to consume remaining conjuncts, substituting
  505.     ;; the appropriate bindings into the remaining conjuncts for each recursion.
  506.     (mapcan #'(lambda (binding-extension)
  507.                 (declare (list binding-extension))
  508.                 ;; Recurse to consume remaining conjuncts, bound by each extension.
  509.                 ;; Note (append binding-extension previous-bindings) didn't work!
  510.                 (retrieve-and 
  511.                  (substitute-bindings binding-extension (rest and-goals))
  512.                  data-dnet rules-dnet (append previous-bindings binding-extension)
  513.                  active-bindings))
  514.             ;; All ways to satisfy the first conjunct.
  515.             (retrieve-bindings 
  516.              (first and-goals) data-dnet rules-dnet active-bindings))))
  517.  
  518. (defun RETRIEVE-OR (or-goals data-dnet rules-dnet active-bindings)
  519.   (declare (list or-goals active-bindings) (symbol data-dnet rules-dnet)
  520.            (optimize (safety 1) (space 2) (speed 3)))
  521.   ;; Since disjunctive, can split into separate calls for each disjunct
  522.   ;; and combine results with no worry about coordinating variables.  
  523.   ;; Don't bother checking for duplicates: that is done elsewhere.
  524.   (mapcan #'(lambda (disjunct) (declare (list disjunct))
  525.               (retrieve-bindings disjunct data-dnet rules-dnet active-bindings))
  526.           or-goals))
  527.  
  528. ;;;------------------------------------------------------------------------
  529. ;;; Version which returns support tree.
  530.  
  531. (defun SUPPORT-ARCS (goal data-dnet rules-dnet record-failure
  532.                                    include-datum-just active-bindings)
  533.   ;; Dispatches analogous to REFERENCE-BINDINGS (see); Returns a list of arcs.
  534.   (declare (list goal active-bindings) (symbol data-dnet rules-dnet)
  535.            (optimize (safety 1) (space 2) (speed 3)))
  536.   (case (first goal)
  537.     ((:and)    (support-and goal data-dnet rules-dnet record-failure
  538.                             include-datum-just active-bindings))
  539.     ((:seq)    (support-seq goal data-dnet rules-dnet record-failure
  540.                             include-datum-just active-bindings))
  541.     ((:or)     (support-or goal data-dnet rules-dnet record-failure
  542.                            include-datum-just active-bindings))
  543.     ((:lisp)   (support-lisp (rest goal) record-failure))
  544.     ((:bind)   (support-bind (second goal) (rest (rest goal))))
  545.     (otherwise (support-pattern goal data-dnet rules-dnet record-failure
  546.                                 include-datum-just active-bindings))))
  547.  
  548. (defun SUPPORT-PATTERN (goal data-dnet rules-dnet record-failure
  549.                                    include-datum-just active-bindings)
  550.   ;; Returns list of arcs supporting (whether directly or by rule application) 
  551.   ;; a goal which doesn't start with an interpreted operator.
  552.   (declare (list goal active-bindings) (symbol data-dnet rules-dnet)
  553.            (optimize (safety 1) (space 2) (speed 3)))
  554.   (let ((success nil) (support-arcs nil))
  555.        (declare (list support-arcs))
  556.        ;; Initialize support list to direct matches in data-dnet.
  557.        (multiple-value-bind
  558.          (results bindings) (dnet::match-pattern-internal goal data-dnet nil)
  559.          (declare (list results bindings))
  560.          (when results
  561.            (setq success t)
  562.            (do ((rptr results (rest rptr)) (bptr bindings (rest bptr)))
  563.                ((null rptr))
  564.              (declare (list rptr bptr))
  565.              (if include-datum-just
  566.                (setf support-arcs 
  567.                      (nconc (datum-justification-arcs (first rptr) (first bptr) data-dnet)
  568.                             support-arcs))
  569.                (push (make-trj-arc :warrant  ':asserted 
  570.                                    :grounds  (list (make-trj-node 
  571.                                                     :claim (first rptr)
  572.                                                     :modality ':supported
  573.                                                     :support nil))
  574.                                    :bindings (first bptr))
  575.                      support-arcs)))))
  576.        ;; Get list of TRJ-ARCs to subtrees from back chaining and add these.
  577.        (multiple-value-bind
  578.          (backchaining-success backchaining-support-arcs)
  579.          (support-backchain goal data-dnet rules-dnet record-failure 
  580.                             include-datum-just active-bindings)
  581.          (declare (list backchaining-support-arcs))
  582.          (if backchaining-success (setq success t))
  583.          ;; Prefer to keep the easier support up front; also preserve order.
  584.          ;; (Do NOT need to test (or backchaining-success record-failure) here!)
  585.          (setf support-arcs 
  586.                (merge-support-arcs support-arcs backchaining-support-arcs)))
  587.        ;; All done.
  588.        (values success support-arcs)))
  589.  
  590. (defun SUPPORT-BACKCHAIN (goal data-dnet rules-dnet record-failure
  591.                                include-datum-just active-bindings)
  592.   ;; Returns a success predicate and arcs to subtrees resulting from back chaining.
  593.   (declare (list goal active-bindings) (symbol data-dnet rules-dnet)
  594.            (optimize (safety 1) (space 2) (speed 3)))
  595.   
  596.   ;; Find matching consequents.  Iterate over each of their antecedents (recorded
  597.   ;; in rule-records).  This iteration is over an implicit disjunction, and each 
  598.   ;; consequent & antecedent pair may support new data independently of others.
  599.   (multiple-value-bind 
  600.     (consequents consequent-bindings reverse-bindings)
  601.     (match-rules goal rules-dnet)
  602.     (declare (list consequents consequent-bindings reverse-bindings))
  603.  
  604.     ;; Loop for consequents matched.
  605.     (do ((cptr consequents         (rest cptr))
  606.          (bptr consequent-bindings (rest bptr))
  607.          (rptr reverse-bindings    (rest rptr))
  608.          (goal-has-variables (pattern-p goal))
  609.          (success nil) (support-arcs nil))
  610.         ((null cptr) (values success support-arcs))
  611.       (declare (list cptr bptr rptr support-arcs))
  612.  
  613.       ;; Loop for antecedents indexed under this consequent.
  614.       (dolist (rule-record (dnet::expr-info-internal (first cptr) rules-dnet))
  615.         (declare (list rule-record))
  616.         
  617.         ;; The following avoids circularity in rules by preventing repeated bindings.
  618.         (unless (circular-bindings (first bptr) (first rptr)
  619.                                    active-bindings goal-has-variables)
  620.           (trace-backward-rule goal rule-record (first bptr))
  621.  
  622.           ;; Substitute bindings to construct subgoals, and substitute returned
  623.           ;; bindings into goal/consequent bindings. See RETRIEVE-BACKCHAIN.
  624.           (let ((subgoal (substitute-bindings (first rptr) 
  625.                                               (rule-record-pattern rule-record))))
  626.             (declare (list subgoal))
  627.             (multiple-value-bind
  628.               (success-this-time new-support-arcs)
  629.               (support-arcs 
  630.                subgoal data-dnet rules-dnet record-failure include-datum-just
  631.                (extend-active-bindings (first bptr) (first rptr) active-bindings))
  632.               (declare (list new-support-arcs))
  633.               (if success-this-time (setq success t))
  634.               (dolist (sa new-support-arcs)
  635.                 (declare (type trj-arc sa))
  636.                 (setf support-arcs 
  637.                       (adjoin-support-arc
  638.                        (make-trj-arc
  639.                         :warrant (rule-record-rule-name rule-record)
  640.                         :grounds  (list (make-trj-node
  641.                                          :claim subgoal
  642.                                          :modality (trj-arc-modality sa)
  643.                                          :support  (list sa)))
  644.                         :bindings (utils:compose-mappings (first bptr)
  645.                                                           (trj-arc-bindings sa)))
  646.                        support-arcs))))))))))
  647.  
  648. ;;; We must return multiple arcs with warrant :AND supporting the goal.  Each 
  649. ;;; arc must have a consistently bound set of support for the conjuncts, and 
  650. ;;; there may be many ways to satisfy the conjuncts.  Conceptually, the idea 
  651. ;;; is to find support for the first conjunct; then split this node into K nodes 
  652. ;;; where K is the number of distinct ways to support it; then recurse to 
  653. ;;; consume remaining conjuncts with each of K bindings substituted into them; 
  654. ;;; then combine the lists of nodes returned.
  655.  
  656. (defun SUPPORT-AND (and-goal data-dnet rules-dnet record-failure
  657.                              include-datum-just active-bindings)
  658.   (declare (list and-goal active-bindings) (symbol data-dnet rules-dnet)
  659.            (optimize (safety 1) (space 2) (speed 3)))
  660.   ;; Just getting things started.
  661.   (support-conjunction-arcs 
  662.    (make-trj-arc :warrant ':and :grounds nil :bindings nil)
  663.    (rest and-goal) data-dnet rules-dnet 
  664.    record-failure include-datum-just active-bindings))
  665.  
  666. ;;; :SEQ will be treated identically except short circuiting on failure.
  667.  
  668. (defun SUPPORT-SEQ (and-goal data-dnet rules-dnet record-failure
  669.                              include-datum-just active-bindings)
  670.   (declare (list and-goal active-bindings) (symbol data-dnet rules-dnet)
  671.            (optimize (safety 1) (space 2) (speed 3)))
  672.   ;; Just getting things started.
  673.   (support-conjunction-arcs 
  674.    (make-trj-arc :warrant ':seq :grounds nil :bindings nil)
  675.    (rest and-goal) data-dnet rules-dnet 
  676.    record-failure include-datum-just active-bindings))
  677.  
  678. (defun SUPPORT-CONJUNCTION-ARCS (arc goals data-dnet rules-dnet record-failure 
  679.                                      include-datum-just active-bindings)
  680.   ;; Takes an AND or :SEQ arc and some goals to be consumed, and returns list of 
  681.   ;; support arcs which constitute the "split" of the arc into its extensions to
  682.   ;; include the remaining conjuncts.
  683.   (declare (list goals active-bindings) (symbol data-dnet rules-dnet)
  684.            (optimize (safety 1) (space 2) (speed 3)))
  685.   (if (null goals)
  686.     (let ((supported (eq (trj-arc-modality arc) ':supported)))
  687.       (values supported (if (or supported record-failure) (list arc))))
  688.  
  689.     ;; Find all ways to satisfy the first conjunct.  Previous bindings are assumed
  690.     ;; to have already been substituted into remaining conjuncts, which guarantees
  691.     ;; consistency.  However, there may still be variables in the conjunct.
  692.     (multiple-value-bind
  693.       (first-conjunct-success support-arcs)
  694.       (support-arcs (first goals) data-dnet rules-dnet record-failure
  695.                     include-datum-just active-bindings)
  696.       (declare (list support-arcs))
  697.       (if (or first-conjunct-success
  698.               (and record-failure (eq (trj-arc-warrant arc) ':and)))
  699.         ;; Split arc into list of arcs, each with extended support and bindings.
  700.         (let ((split-arcs
  701.                (if support-arcs
  702.                  (mapcar
  703.                   #'(lambda (sa) (declare (type trj-arc sa))
  704.                      (make-trj-arc
  705.                       :warrant (trj-arc-warrant arc)
  706.                       ;; Retain conjunct order. Reusing list elsewhere (no nconc).
  707.                       :grounds (append (trj-arc-grounds arc)
  708.                                        (list (make-trj-node
  709.                                               :claim (first goals)
  710.                                               :modality (trj-arc-modality sa)
  711.                                               :support (list sa))))
  712.                       :bindings (append (trj-arc-bindings arc)
  713.                                         (trj-arc-bindings sa))))
  714.                   support-arcs)
  715.                  (list
  716.                   (make-trj-arc
  717.                    :warrant (trj-arc-warrant arc)
  718.                    :grounds (append (trj-arc-grounds arc)
  719.                                     (list (make-trj-node
  720.                                            :claim (first goals)
  721.                                            :modality :unsupported
  722.                                            :support nil)))
  723.                    :bindings (append (trj-arc-bindings arc) (list nil)))))))
  724.           ;; Recurse on remaining conjuncts with each separate binding substituted
  725.           ;; in, then combine results.  (But skip failure arcs in :SEQ.)
  726.           (do ((sa-ptr split-arcs (rest sa-ptr))
  727.                (success nil) (results (list ':head)))
  728.               ((null sa-ptr) (values success (rest results)))
  729.             ;; If the conjunct just consumed is supported, ok to try remainder.
  730.             ;; :AND lets us try even if it is not supported, to build rest of tree.
  731.             (if (or (eq (trj-arc-modality (first sa-ptr)) ':supported)
  732.                     (eq (trj-arc-warrant arc) ':and)) ; record-failure must be true
  733.               (multiple-value-bind
  734.                 (recursive-success recursive-support-arcs)
  735.                 (support-conjunction-arcs 
  736.                  (first sa-ptr) 
  737.                  (substitute-bindings (trj-arc-bindings (first sa-ptr))
  738.                                       (rest goals))
  739.                  data-dnet rules-dnet record-failure 
  740.                  include-datum-just active-bindings)
  741.                 (if recursive-success (setq success t))
  742.                 (when (or recursive-success record-failure)
  743.                   (nconc results recursive-support-arcs)))
  744.               ;; Unsupported, operator :seq, and record-failure T:
  745.               (nconc results
  746.                      (list (make-trj-arc
  747.                             :warrant (trj-arc-warrant arc)
  748.                             :grounds (append (trj-arc-grounds arc)
  749.                                              (list (make-trj-node 
  750.                                                     :claim (first goals)
  751.                                                     :modality :unsupported
  752.                                                     :support support-arcs)))
  753.                             :bindings (trj-arc-bindings arc)))))))
  754.         (if record-failure ; it is :seq and failed
  755.           (values nil
  756.                   (list
  757.                    (make-trj-arc
  758.                     :warrant :seq
  759.                     :grounds (append (trj-arc-grounds arc)
  760.                                      (list (make-trj-node
  761.                                             :claim (first goals)
  762.                                             :modality :unsupported
  763.                                             :support nil)))
  764.                     :bindings (trj-arc-bindings arc))))
  765.           (values nil nil))
  766.         ))))
  767.  
  768. (defun SUPPORT-OR (or-goal data-dnet rules-dnet record-failure
  769.                                      include-datum-just active-bindings)
  770.   ;; Returns a list of a single TRJ arc, whose grounds correspond to disjuncts.
  771.   (declare (list or-goal active-bindings) (symbol data-dnet rules-dnet)
  772.            (optimize (safety 1) (space 2) (speed 3)))
  773.   ;; Since disjunctive, can split into separate calls for each disjunct
  774.   ;; and combine results with no worry about coordinating variables.
  775.   ;; Don't bother checking for duplicates: that is done elsewhere.
  776.   (do ((goal-ptr (cdr or-goal) (cdr goal-ptr))
  777.        (supported nil)
  778.        (grounds (list :head))
  779.        (bindings (list :head)))
  780.       ((null goal-ptr) (values supported 
  781.                                (list (make-trj-arc :warrant :or 
  782.                                                    :grounds (rest grounds)
  783.                                                    :bindings (rest bindings)))))
  784.       (declare (list goal-ptr grounds bindings))
  785.       (multiple-value-bind
  786.         (success support-arcs)
  787.         (support-arcs (first goal-ptr) data-dnet rules-dnet record-failure
  788.                       include-datum-just active-bindings)
  789.         (declare (list support-arcs))
  790.         (if success (setf supported t))
  791.         (when (or success record-failure)
  792.           (nconc grounds (list (make-trj-node
  793.                                   :claim    (first goal-ptr)
  794.                                   :modality (if success :supported :unsupported)
  795.                                   :support support-arcs)))
  796.           (nconc bindings (list (mapcar #'trj-arc-bindings support-arcs)))))))
  797.  
  798. (defun SUPPORT-LISP (forms record-failure)
  799.   (declare (list forms) (optimize (safety 1) (space 2) (speed 3)))
  800.   ;; Success depends on results; there are no bindings.
  801.   (let ((success (lisp-eval forms)))
  802.     (values success
  803.             (if (or success record-failure)
  804.               (list (make-trj-arc 
  805.                      :warrant ':lisp 
  806.                      :grounds (list (make-trj-node 
  807.                                      :claim forms
  808.                                      :modality (if success :supported :unsupported)
  809.                                      :support nil))
  810.                      :bindings nil))))))
  811.  
  812. (defun SUPPORT-BIND (variable forms)
  813.   (declare (symbol variable) (list forms) 
  814.            (optimize (safety 1) (space 2) (speed 3)))
  815.   ;; Always succeeds; return an arc that provides bindings.
  816.   (let ((result (lisp-eval forms)))
  817.     (values t
  818.             (list (make-trj-arc 
  819.                    :warrant ':bind 
  820.                    :grounds (list (make-trj-node
  821.                                    :claim forms
  822.                                    :modality ':supported
  823.                                    :support nil))
  824.                    :bindings (list (cons variable result)))))))
  825.  
  826. (defun DATUM-JUSTIFICATION-NODE (ground bindings data-dnet)
  827.   (make-trj-node :claim ground
  828.                  :modality :supported
  829.                  :support (datum-justification-arcs ground bindings data-dnet)))
  830.  
  831. (defun DATUM-JUSTIFICATION-ARCS (datum bindings data-dnet)
  832.   (mapcar #'(lambda (datum-just)
  833.               (make-trj-arc :warrant  (justification-warrant datum-just)
  834.                             :grounds  (list (datum-justification-node 
  835.                                              ;; unify may be bogus.  More correct
  836.                                              ;; to do it to the rule.
  837.                                              (justification-grounds datum-just)
  838.                                              (unify datum (justification-grounds datum-just))
  839.                                              data-dnet))
  840.                             :bindings bindings))
  841.           (datum-justification datum data-dnet)))
  842.  
  843. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  844. ;;;
  845. ;;;                        USER INTERFACE FUNCTIONS
  846. ;;;
  847. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  848.  
  849. ;;;------------------
  850. ;;; Backward Chaining
  851.  
  852. (defun SUPPORTED (goal data rules)
  853.   "supported <goal> <data> <rules>                                 [Function]
  854.   Returns non-NIL value iff <goal> is supported by <data> and <rules>."
  855.   (declare (inline retrieve-bindings))
  856.   (check-type data symbol)
  857.   (check-type rules symbol)
  858.   (assert (sm:gets 'dnet data) (data)
  859.           "[DNET:SUPPORTED] ~S is not a known DNET." data)
  860.   (assert (sm:gets 'dnet rules) (rules) 
  861.           "[DNET:SUPPORTED] ~S is not a known DNET." rules)
  862.   (if *rule-trace* (format *rule-trace* "~&---------- Call to SUPPORTED:"))
  863.   (retrieve-bindings goal data rules nil))
  864.  
  865. (defun RETRIEVE (goal data rules)
  866.   "retrieve <goal> <data> <rules>                                  [Function]
  867.   Given <goal> is a pattern, returns two values: a list of expressions
  868.   satisfying the pattern, and a list of bindings by which each expression
  869.   unifies with <goal>."
  870.   (declare (inline retrieve-bindings))
  871.   (check-type data symbol)
  872.   (check-type rules symbol)
  873.   (assert (sm:gets 'dnet data) (data) 
  874.           "[DNET:RETRIEVE] ~S is not a known DNET." data)
  875.   (assert (sm:gets 'dnet rules) (rules) 
  876.           "[DNET:RETRIEVE] ~S is not a known DNET." rules)
  877.   (if *rule-trace* (format *rule-trace* "~&---------- Call to RETRIEVE:"))
  878.   (let ((bindings nil) (results nil))
  879.     (declare (list bindings results))
  880.     ;; Get bindings for all ways the goal is met.
  881.     (dolist (binding-set (retrieve-bindings goal data rules nil))
  882.       (declare (list binding-set))
  883.       ;; Substitute unique bindings into goal to get results.
  884.       (unless (member binding-set bindings :test #'equal)
  885.           (push (substitute-bindings binding-set goal) results)
  886.           (push binding-set bindings)))
  887.     (values results bindings)))
  888.  
  889. (defvar *SUPPORT-TREE* nil 
  890.   "SUPPORT stashes the most recent root TRJ-NODE here, for debugging.")
  891.  
  892. (defun SUPPORT (goal data rules
  893.                      &key (record-failure nil) (include-datum-justification nil))
  894.   "support <goal> <data> <rules> 
  895.          &key <record-failure> <include-datum-justification>         [Function]
  896.   Given <goal> is a pattern, returns two values: a boolean T or NIL saying
  897.   whether the <goal> is supported, and a TRJ-NODE which is the root of its
  898.   support tree.  When the first value is NIL, the partial support tree is
  899.   returned only if <record-failure> is T.  If <include-datum-justification>
  900.   is T, the support tree includes justifications recorded in the <data> DNET."
  901.   (declare (inline support-arcs))
  902.   (check-type data symbol)
  903.   (check-type rules symbol)
  904.   (assert (sm:gets 'dnet data) (data) 
  905.           "[DNET:SUPPORT] ~S is not a known DNET." data)
  906.   (assert (sm:gets 'dnet rules) (rules) 
  907.           "[DNET:SUPPORT] ~S is not a known DNET." rules)
  908.   (if *rule-trace* (format *rule-trace* "~&---------- Call to SUPPORT:"))
  909.   (multiple-value-bind 
  910.     (success support-arcs)
  911.     (support-arcs goal data rules record-failure include-datum-justification nil)
  912.     (declare (list support-arcs))
  913.     (values success 
  914.             (setq *support-tree*
  915.                   (make-trj-node 
  916.                    :claim goal 
  917.                    :modality (if success :supported :unsupported) 
  918.                    :support (if (or success record-failure) support-arcs))))))
  919.  
  920. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  921. (provide :rule-back)
  922. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  923. ;;; the end.